EVENT_TROOPS_PLACE = 0				#player puts troops in a region
EVENT_HARBOUR = 1					#player builds a harbour
EVENT_ATTACK = 2					#player attacks another country
EVENT_CONVERT = 3					#player converts a country (can be preceded by an attack)
EVENT_TROOPS_PREPARE_MOVE = 4		#player moves troops from one region to another
EVENT_TROOPS_MOVE = 5				#player moves troops from one region to another

EVENT_ATTACK_FAIL_TO_STRONG = -1				#The attack failed because the target was too strong.
EVENT_ATTACK_FAIL_TO_FAR = -2					#The attack failed because the target was too far
EVENT_TROOPS_PLACE_FAIL_DONT_OWN = -3			#don't own country placing troops in
EVENT_TROOPPS_MOVE_FAIL_DONT_OWN_ORIGIN = -4	#don't own country moving troops from
EVENT_TROOPPS_MOVE_FAIL_DONT_OWN_TARGET = -5	#don't own country moving troops to
EVENT_TROOPS_MOVE_FAIL_TOO_FAR = -6				#can't reach country moving troops to


class Gameplay

	attr_accessor :countries, :lakes, :map, :events
	attr_reader :players, :turnState, :currentPlayer

	@@CLICKSTATE_NONE = 0
	@@CLICKSTATE_SELECTED = 1
	
	@@TURNSTATE_PLACE = 0
	@@TURNSTATE_ATTACK = 1
	@@TURNSTATE_MOVE = 2
	


	def initialize(_map, _numCountries, _numLakes, _countryNames, _waterNames, _troopCounts, _players)

		@map = _map
		@countries = []
		@lakes = []
		@players = _players
		
		@waterTroopStrength = 0.5
		@reinforcements = 3

		
		@events = Queue.new
			
		#current player number (0-based)
		#0 is no player, 1-6 are players
		@currentPlayer = 1
		
		
		for count in (0.._numCountries-1)
			r =  Country.new(_countryNames[count], _troopCounts[count])
			r.neighbours = createNeighboursList(count + 1)
			@countries << r

		end
		
		for count in (0.._numLakes-1)
			r = Lake.new(_waterNames[count])
			r.neighbours = createNeighboursList(WATERBODY_START + 1 + count)
			@lakes << r
			
		end
		
		@selected_country_index = nil
		@clickState = @@CLICKSTATE_NONE
		@turnState = @@TURNSTATE_PLACE
		
		
	end
	
	
	def leftButton(region, parameters)
		

				
		#select country
		return if region >= WATERBODY_START
	
		case @turnState
			
			when @@TURNSTATE_PLACE
			
				#place some number of troops here
				#troopsToAdd was calculated before moving to TURNSTATE_PLACE
				@selected_country_index = region - 1
				
				if @countries[@selected_country_index].owner == @currentPlayer
					@countries[@selected_country_index].troops += @reinforcements * countCountriesForPlayer(@currentPlayer)
					@events << [EVENT_TROOPS_PLACE, [@selected_country_index]]
				
					advanceTurnState
				else
					@events << [EVENT_TROOPS_PLACE_FAIL_DONT_OWN, [@selected_country_index]]
				end
						
			when @@TURNSTATE_ATTACK


				@selected_country_index = region - 1
				
				if @countries[@selected_country_index].owner == @currentPlayer #playerWhoseTurnItIs
				
				puts "-harbour"
				
					#build harbour if no harbour and on water
					#@clickState = @@CLICKSTATE_NONE
					
					canBuildHarbour = false
					@countries[@selected_country_index].neighbours.each {|r|
						canBuildHarbour = true if r >= WATERBODY_START
					}
					
					puts " -canBuild " + canBuildHarbour.to_s
					
					if canBuildHarbour == true
						@events << [EVENT_HARBOUR, [@selected_country_index]]
					
						@countries[@selected_country_index].harbour = true
						@selected_country_index = nil
					
						advanceTurnState
					end
					
				else
				
				puts "-attack"

					#if atacker doesn't own attacked country
					
					#attack the country clicked on (if possible)
					result = attack(@currentPlayer, @selected_country_index)
					puts " -result " + result.to_s
					
					if result > 0
					
						@events << [EVENT_ATTACK, [@currentPlayer, @selected_country_index]]
						
						if result == 2
							@events << [EVENT_CONVERT, [region-1]]
						end
						
						advanceTurnState
					
					else
					
						#failure in attack() returns the proper fail event code
						@events << [result, [@currentPlayer, @selected_country_index]]
					
					end

					@selected_country_index = nil					

				end
				
			when @@TURNSTATE_MOVE
			
				if @selected_country_index == nil
				
					if @countries[region-1].owner == @currentPlayer
						@selected_country_index = region - 1
						@events << [EVENT_TROOPS_PREPARE_MOVE, [@selected_country_index]]
					else
						@events << [EVENT_TROOPPS_MOVE_FAIL_DONT_OWN_ORIGIN, [@selected_country_index]]
					end
					
				else
					#queue a move event for the GUI - indicate the from and to regions
					
					
					#do some kind of move thing!
					#element in parameters array will indicate how many troops to move
					#if parameters[0] != nil and parameters[0] < WATERBODY_START
		
					n = getNeighboursByPlayer(@currentPlayer, region-1)
					w = getWaterNeighboursByPlayer(@currentPlayer, region-1, true)
					
					puts "N", n, "", "W", w, "", ""
					
					n = (n + w).uniq
					
					canMove = false
					#temp hack to allow moving troops from a country to itself
					#theres no 'pass' button yet
					canMove = true if @selected_country_index == region-1
					n.each {|country|
					
						canMove = true if country == @selected_country_index and @countries[country].owner == @currentPlayer
					
					}
						
					if canMove == true
		
						if @countries[@selected_country_index].troops < parameters[0]
							parameters[0] = @countries[@selected_country_index].troops
						end
						
						countries[@selected_country_index].troops -= parameters[0]
						countries[region-1].troops += parameters[0]
						@events << [EVENT_TROOPS_MOVE, [@selected_country_index, region - 1]]
						
						#advance state
						advanceTurnState
					else
						@selected_country_index = nil
					end
						
				end
			
		end #case
			
	
	end
	
	def advanceTurnState
	
		case @turnState
		
			when @@TURNSTATE_PLACE
			
				#advance to turnstate_attack
				@turnState = @@TURNSTATE_ATTACK
				
			when @@TURNSTATE_ATTACK
			
				#advance to turnstate_move
				@turnState = @@TURNSTATE_MOVE
				
			when @@TURNSTATE_MOVE
			
				#advance player
				@currentPlayer += 1
				@currentPlayer = 1 if @currentPlayer > @players
				
				#calculate troops to give next players
				#@troopsToAdd = calcTroopsToAdd(@currentPlayer)
								
				#reset to turnstate_place
				@turnState = @@TURNSTATE_PLACE
				
		
		end
	
	end	
	
	def createNeighboursList(country)
		
		#country - int value of country - 1 over index
	
		neighbours = []
	
		for x in (0..@map.width-1)
			for y in (0..@map.height-1)
				
				#if this cell belongs to the right country
				if @map.cell(x, y) == country then
				
					neighbours << @map.cell(x-1,y)-1 if x > 0 and @map.cell(x-1,y) != country
					neighbours << @map.cell(x,y-1)-1 if y > 0 and @map.cell(x,y-1) != country
					
					neighbours << @map.cell(x+1,y)-1 if x < @map.width-1 and @map.cell(x+1,y) != country
					neighbours << @map.cell(x,y+1)-1 if x < @map.height-1 and @map.cell(x,y-1) != country
				
				end
				
			end #inner loop
		end #outer loop

		#remove dupes
		neighbours.uniq!
		
		#remove self
		neighbours = neighbours.delete_if {|item| item == country}
		
		return neighbours
			
	end
	
	#returns regions bordering country by land owned by player
	def getNeighboursByPlayer(player, country)
		
		#-1 for all players
		
		results = []

		#get neighbours, depending on country or lake
		if country >= WATERBODY_START
			n = @lakes[country - WATERBODY_START].neighbours
		else
			n = @countries[country].neighbours
		end

		n.each {|neighbour|

		
			if neighbour < WATERBODY_START
				results << neighbour if @countries[neighbour].owner == player or player == -1
			end
		
		}
		
		return results
	
	end
	
	#gets bodies of water bordering a coutnry
	def getNeighbourWater(country)
		
		results = []

		@countries[country].neighbours.each {|neighbour|

		
			if neighbour >= WATERBODY_START
				results << neighbour
			end
		
		}
		
		return results
	
	end
	
	#get the neighbours of country owned by player that are neighbours by water
	#will include some land neighbours if they are also water neighbours
	def getWaterNeighboursByPlayer(player, country, harboursOnly = false)
	
		waterNeighbours = []
	
		#get adjoining bodies of water
		waters = getNeighbourWater(country)
		
		#each body of water
		waters.each{ |water|
			neighbours = getNeighboursByPlayer(player, water)
			
			#each neighbour on each body of water is added if it has
			#a harbour or if harboursOnly is false
			neighbours.each{ |n|
				waterNeighbours << n if @countries[n].harbour == true or not harboursOnly
			}
		}
		
		waterNeighbours.uniq!
		
		return waterNeighbours
		
	
	end

	
	#gets the number of troops that player can attack country with
	def getNeighboursTroopsByPlayer(player, country)
	
		troops = 0
	
		neighbours = getNeighboursByPlayer(player, country)
		
		neighbours.each {|neighbour|
		
			troops += @countries[neighbour].troops
		
		}
		
		#get water neighbours of country that are owned by player, and 
		#have harbours
		waterNeighbours = getWaterNeighboursByPlayer(player, country, true)
		
		#remove any neighbours from water neighbour list
		waterNeighbours = waterNeighbours - neighbours
		
		waterNeighbours.each {|n|
		
			troops += @countries[n].troops * @waterTroopStrength
		
		}
		
		return troops
	
	end
	
	def attack(player, country_to)
	

		to = @countries[country_to]
		
	
		attackTroops = getNeighboursTroopsByPlayer(player, country_to)
		defenseTroops = getNeighboursTroopsByPlayer(to.owner, country_to)
	
	
		result = 0
	
		if isPlayerNeighbour(player, country_to)

			#if the country is unowned, claim it
			if to.owner == 0
				to.owner = player
				return 2
			end
				
			#number of more troops that 'from 'has
			diff = attackTroops - defenseTroops
		
			#if 'from' has more troops than 'to'
			if diff > 0
			
				result = 1
			
				#reduce troop levels in 'to'
				to.troops -= diff
				
				#if 'to' has less than no troops, switch owner
				if to.troops <= 0
					result = 2
					to.owner = player
					to.troops = 0
				end
			else
			
				return EVENT_ATTACK_FAIL_TO_STRONG
			
			end
		
		else
		
			return EVENT_ATTACK_FAIL_TO_FAR
		
		end
		
		return result
	
	end
	
	#are two countried neighbours
	def isNeighbour(c_from, c_to)
	
		bneighbour = false	
	
		from = @countries[c_from]
		from.neighbours.each{ |neighbour|
		
			bneighbour = true if c_to == neighbour
		
		}
		
		return bneighbour
	
	end
	
	#does player have countries that border country c_to?
	def isPlayerNeighbour(player, c_to)
	
		bneighbour = false	
	
		#get complete neighbours list
		n = getNeighboursByPlayer(player, c_to)
		n += getWaterNeighboursByPlayer(player, c_to, true)
		n.uniq!
		
		n.each{ |neighbour|
		
			if neighbour < WATERBODY_START

				bneighbour = true if player == @countries[neighbour].owner
			end
		
		}
		
		return bneighbour
	
	end
	
	def countCountriesForPlayer(player)
	
		count = 0
		
		@countries.each { |country|
		
			count += 1 if country.owner == player
		
		}
		
		return count
	
	end

end


#use this?
class MapSettings

 	attr_accessor :sizeX, :sizeY, :numCountries, :islandStyle, :coastPercentKeep, :averageCountrySize, :countryProportion, :countryIrregularity, :minLakeSize

	def initialize

		@sizeX = 66
		@sizeY = 45
		@numCountries = 30
		@islandStyle = ISLAND_STYLE_SOME
		@coastPercentKeep = 50
		@averageCountrySize = 100
		@countryProportion = 70
		@countryIrregularity = 20
		@minLakeSize = 10

	end

end
